<template>
  <div :width="width" :height="height" :data="data" :style="[baseStyles]">
    <div style="white-space: nowrap; overflow: hidden;">
      <div :style="[{'display': 'inline-block'},marqueeStyles]">
        <span style="display: inline-block;" ref="marqueeText">
          {{(data[0]&&data[0].__value)||''}}
          <i style="display:inline-block;width:5em;"></i>
        </span>
        <span style="display: inline-block;" v-if="scollShow">
          {{(data[0]&&data[0].__value)||''}}
          <i style="display:inline-block;width:5em;"></i>
        </span>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "marquee",
  props: {
    width: {
      type: Number
    },
    height: {
      type: Number
    },
    data: {
      type: Array,
      default: () => []
    },
    opts: {
      type: Object,
      default: () => {}
    },
    padding: {
      type: Object,
      default: () => {}
    }
  },
  computed: {
    baseStyles() {
      // 基础样式
      return Object.assign({}, this.textStyle, {
        fontSize: this.textStyle.fontSize + "px",
        width: this.width + "px",
        height: this.height + "px",
        pointerEvents: "auto"
      });
    },
    marqueeStyles() {
      // 滚动样式
      return {
        transform: this.transform,
        transition: this.transition
      };
    },
    watchItmes() {
      const {
        loop,
        width,
        duration,
        ifSpeed,
        textStyle,
        leading,
        subordinate
      } = this;
      let fontSize = textStyle.fontSize;
      return {
        loop,
        width,
        duration,
        leading,
        ifSpeed,
        fontSize,
        subordinate
      };
    }
  },

  mounted() {
    // 判断是否需要启动跑马灯
    this.marqueeRun();
  },

  // 观察
  watch: {
    watchItmes: "watchChange",
    data: {
      handler(newValue, oldValue) {
        if (newValue[0]) {
          this.watchChange();
        }
      },
      deep: true
    }
  },
  methods: {
    // 观察改变
    watchChange() {
      this.clearAllTimeout();
      this.$nextTick(() => {
        this.marqueeRun();
      });
    },
    clearAllTimeout() {
      // 清楚定时器
      this.marqueeTimeOut && clearTimeout(this.marqueeTimeOut);
      this.leadingTimeout && clearTimeout(this.leadingTimeout);
      this.subordinateTimeout && clearTimeout(this.subordinateTimeout);

      this.transform = `translateX(0px)`;
      this.transition = `none 0s ease 0s`;
    },
    marqueeRun() {
      this.marqueeTextWidth = this.$refs.marqueeText.offsetWidth;
      if (this.marqueeTextWidth > this.width && this.loop) {
        this.leadingAction(); // 跑起来
      } else {
        this.scollShow = false;
      }
    },
    marqueeAction() {
      // 跑动的 判断是不是定速  因为这里不需要实时的改变 所以不需要再watch 里面监控 ifSpeed 的变化 等定时器停止之后去监控
      let transitionTime = this.ifSpeed
        ? this.marqueeTextWidth * (this.speed / 100)
        : this.duration;
      this.transform = `translateX(${-this.marqueeTextWidth}px)`;
      this.transition = `transform ${transitionTime}ms linear 0s`;
      // none 0s ease 0s
      this.marqueeTimeOut = setTimeout(() => {
        this.subordinateAction();
      }, transitionTime);
    },
    // 轮播开始的事件
    leadingAction() {
      this.leadingTimeout = setTimeout(() => {
        this.marqueeAction();
      }, this.leading);
    },
    subordinateAction() {
      // 轮播结束的事件
      this.subordinateTimeout = setTimeout(() => {
        // 因为loop会从false 变成true 要重新启动
        // 不是轮播直接停止
        this.transform = `translateX(0px)`;
        this.transition = `none 0s ease 0s`;
        this.loop && this.leadingAction();
      }, this.subordinate);
    }
  },
  data() {
    return {
      scollShow: true,
      duration: 8000, // 非定速下的动画时间
      transform: "",
      transition: "",
      ifSpeed: false, // 是否启动定速
      leading: 1000, // 轮播开始钱暂停的时间
      loop: true, // 是否循环
      speed: 1000, // 定速的动画间隔
      subordinate: 2000, // 轮播完一次暂停的时间
      textStyle: {
        color: "#000",
        fontFamily: "Microsoft Yahei",
        fontSize: 32,
        fontWeight: "normal"
      } // 文本样式
    };
  }
};
</script>